<template>
  <view class="mPopover"
        :style="{
          '--theme-bg-color':bgStyleColor
        }"
  >
    <view @click.stop="handleClick" class="m-button-popover">
      <slot></slot>
    </view>
    <view
        class="m-popover"
        v-show="inited"
        ref="m-transition"
        :class="[classes,`m-popover-${placement}`]"
        :style="[mergeStyle]"
        @touchmove="noop"
    >
      <view class="m-popover-arrow"
            :style="[arrowStyle]"
            :class="[{
							'm_popper__up':placement.indexOf('bottom')===0,
							'm_popper__arrow':placement.indexOf('top')===0,
							'm_popper__right':placement.indexOf('right')===0,
							'm_popper__left':placement.indexOf('left')===0,
						}]"
      >
      </view>
      <slot name="content">
        <view :class="[{
          'horizontal__action':actionsDirection==='horizontal'
        }]">
          <view
              @click.stop="actionAction(item)"
              v-for="item,index in options"
              class="m-popover__action"
              :class="[{
              'dark__action':theme==='dark'
            }]"
              :key="index">
            <view
                class="m-popover__action-text"
            >{{item.text}}</view>
          </view>
        </view>
      </slot>
    </view>
  </view>
</template>

<script>
const tranClass = {
  enter: "m-fade-zoom-enter m-fade-zoom-enter-active",
  'enter-to': "m-fade-zoom-enter-to m-fade-zoom-enter-active",
  leave: "m-fade-zoom-leave m-fade-zoom-leave-active",
  'leave-to': "m-fade-zoom-leave-to m-fade-zoom-leave-active",
}
export default {
  props:{
    options:{
      type:Array,
      default: ()=>[]
    },
    placement:{
      type:String,
      default:'bottom-start'
    },
    bgColor:{
      type:String,

    },
    // light dark
    theme:{
      type:String,
      default:'light'
    },
    // horizontal vertical
    actionsDirection:{
      type:String,
      default:'vertical'
    }
  },
  name:"Popover",
  watch: {
    show: {
      handler(newVal) {
        newVal ? this.vueEnter() : this.vueLeave()
      },
      // 表示同时监听初始化时的props的show的意思
      immediate: true
    }
  },
  data() {
    return {
      show:false,
      inited: false, // 是否显示/隐藏组件
      classes: '', // 应用的类名
      display: false, // 组件是否展示
      duration:100,
      popoverStyle:{

      },
      arrowOldStyle:{}
    };
  },
  computed:{

    bgStyleColor(){
      if(this.bgColor){
        return this.bgColor
      }
      if(this.theme ==='light'){
        return 'white'
      }
      if(this.theme ==='dark'){
        return '#4a4a4a'
      }
    },

    mergeStyle(){
      return {
        transitionDuration: `${this.duration}ms`,
        transitionTimingFunction: `ease-out`,
        ...this.popoverStyle
      }
    },
    arrowStyle(){
      return {
        ...this.arrowOldStyle
      }
    }
  },
  mounted(){
	// #ifdef H5
	window.addEventListener('click',()=>{
	  this.show = false
	})
	// #endif  
    
  },
  methods:{
    handleClick(){
      if(this.show){
        this.show = false
      }else {
        this.show = true
      }
      this.$emit('handleClick',this.show)
    },
    close(){
      this.show = false
    },
    actionAction(item){
      this.$emit('select',item)
      this.show = false
    },
    sleep(value){
      return new Promise((resolve) => {
        setTimeout(() => {
          resolve()
        }, value)
      })
    },
    vueEnter(){
      this.inited = true
      this.getPosition()
      this.classes = tranClass.enter
      this.$nextTick(async () => {
        await this.sleep(30)
        this.classes = tranClass['enter-to']

      })
    },
    vueLeave(){
      this.classes = tranClass.leave

      this.$nextTick(async () => {
        this.classes = tranClass['leave-to']
        await this.sleep(120)
        this.inited = false
      })
    },
    // 阻止事件冒泡
    preventEvent(e) {
      e && typeof (e.stopPropagation) === 'function' && e.stopPropagation()
    },

    getPosition(){
      return new Promise((resolve) => {
        this.$nextTick(()=>{
          let selectorQuery = uni.createSelectorQuery().in(this).selectAll('.m-button-popover,.m-popover')
          selectorQuery.boundingClientRect(async (data)=>{
            let {left,bottom,right,top,width,height} = data[0]
            let popoverClientRect = data[1]
            let popoverStyle = {}
            let arrowOldStyle ={}

            switch (this.placement) {
              case 'top':
                if(popoverClientRect.width > width){
                  popoverStyle.left = `-${(popoverClientRect.width - width)/2}px`
                }else{
                  popoverStyle.left = `${Math.abs(popoverClientRect.width - width)/2}px`
                }
                popoverStyle.bottom =`${height+8}px`
                arrowOldStyle.left = (popoverClientRect.width/2-6)+'px'
                break;
              case 'top-start':
                popoverStyle.left = `0px`
                popoverStyle.bottom = `${height+8}px`
                arrowOldStyle.left = '16px'
                break;
              case 'top-end':
                popoverStyle.right = `0px`
                popoverStyle.bottom = `${height+8}px`
                arrowOldStyle.right = '16px'
                break;
              case 'bottom':
                if(popoverClientRect.width>width){
                  popoverStyle.left = `-${(popoverClientRect.width - width)/2}px`
                }else{
                  popoverStyle.left = `${Math.abs(popoverClientRect.width - width)/2}px`
                }
                popoverStyle.top =`${height+8}px`
                arrowOldStyle.left = (popoverClientRect.width/2-6)+'px'
                break;
              case 'bottom-start':
                popoverStyle.top = `${height+8}px`
                popoverStyle.left = `0px`
                arrowOldStyle.left = '16px'
                break;
              case 'bottom-end':
                popoverStyle.top = `${height+8}px`
                popoverStyle.right = `0px`
                arrowOldStyle.right = '16px'
                break;
              case 'right':
                popoverStyle.left = `${width+8}px`
                if(popoverClientRect.height>height){
                  popoverStyle.top =`-${(popoverClientRect.height - height)/2}px`
                }else{
                  popoverStyle.top =`${Math.abs((popoverClientRect.height - height)/2)}px`
                }
                arrowOldStyle.top = `${popoverClientRect.height/2-6}px`
                break;
              case 'right-start':
                popoverStyle.left = `${width+8}px`
                popoverStyle.top =`0px`
                arrowOldStyle.top = `8px`
                break;
              case 'right-end':
                popoverStyle.left = `${width+8}px`
                popoverStyle.bottom =`0px`
                arrowOldStyle.bottom = `8px`
                break;
              case 'left':
                popoverStyle.right = `${width+8}px`
                if(popoverClientRect.height>height){
                  popoverStyle.top =`-${(popoverClientRect.height - height)/2}px`
                }else{
                  popoverStyle.top =`${Math.abs((popoverClientRect.height - height)/2)}px`
                }
                arrowOldStyle.top = `${popoverClientRect.height/2-6}px`
                break;
              case 'left-start':
                popoverStyle.right = `${width+8}px`
                popoverStyle.top =`0px`
                arrowOldStyle.top = `8px`
                break;

              case 'left-end':
                popoverStyle.right = `${width+8}px`
                popoverStyle.bottom =`0px`
                arrowOldStyle.bottom = `8px`
                break;
            }

            this.popoverStyle = popoverStyle
            this.arrowOldStyle = arrowOldStyle
            resolve()
          }).exec()
        })
      })
    },
    // 空操作
    noop(e) {
      this.preventEvent(e)
    }
  }
}
</script>

<style lang="scss" scoped>
$theme-bg-color: var(--theme-bg-color);
.mPopover{
  position: relative;
}
.m-button-popover{
  display: inline-block;
}
.m-popover{
  border-radius: 8px;
  z-index: 2144;
  position: absolute;
  background-color: $theme-bg-color;
  box-shadow: 0 2px 12px #3232331f;

}
.m-popover-top{
  transform-origin: 50% bottom;
}
.m-popover-top-start{
  transform-origin: 50% bottom;
}
.m-popover-top-end{
  transform-origin: 0 bottom;
}
.m-popover-bottom{
  transform-origin: 50% 0;
}
.m-popover-bottom-end{
  transform-origin: 100% 0;
}
.m-popover-bottom-start{
  transform-origin: 0 0;
}
.m-popover-right{
  transform-origin: left 50%;
}
.m-popover-right-start{
  transform-origin: left 0;
}
.m-popover-right-end{
  transform-origin: left 100%;
}
.m-popover-left{
  transform-origin: right 50%;
}
.m-popover-left-start{
  transform-origin: right 0;
}
.m-popover-left-end{
  transform-origin: right 100%;
}
.m-popover-arrow{
  position: absolute;
  width: 0;
  height: 0;
  border-color: transparent;
  border-style: solid;
  border-width: 6px;
  color:$theme-bg-color;
}
.m_popper__up{
  border-top-width: 0;
  border-bottom-color: currentColor;
  top: -6px;
}
.m_popper__right{
  border-left-width: 0;
  border-right-color: currentColor;
  left:-5px;
}
.m_popper__left{
  border-right-width: 0;
  border-left-color: currentColor;
  right:-5px;
}
.m_popper__arrow{
  border-bottom-width: 0;
  border-top-color: currentColor;
  bottom: -6px;
}
.m-popover__action{
  position: relative;
  display: flex;
  align-items: center;
  box-sizing: border-box;
  height: 88rpx;
  padding: 0 40rpx;
  font-size: 32rpx;
  cursor: pointer;
}
.m-popover__action-text{
  display: flex;
  flex: 1;
  align-items: center;
  justify-content: center;
  height: 100%;
  padding: 0 30rpx;
  border-bottom:1rpx solid #ebedf0;
  word-wrap: break-word;
  white-space: nowrap;
}
.m-popover__action:last-child{
  .m-popover__action-text{
    border-bottom:none;
  }
}
.dark__action{
  color: white;
  .m-popover__action-text{
    border-bottom:1rpx solid #ebedf033
  }
}
.horizontal__action{
  display: flex;
  .m-popover__action{
    padding: 0 20rpx;
    border-right:1rpx solid #ebedf0;
  }
  .m-popover__action-text{
    padding:0;
    //border-right:1rpx solid #ebedf0;
  }
}


$u-zoom-scale: scale(0.95);

.m-fade-enter-active,
.m-fade-leave-active {
  transition-property: opacity;
}

.m-fade-enter,
.m-fade-leave-to {
  opacity: 0
}

.m-fade-zoom-enter,
.m-fade-zoom-leave-to {
  transform: $u-zoom-scale;
  opacity: 0;
}

.m-fade-zoom-enter-active,
.m-fade-zoom-leave-active {
  transition-property: transform, opacity;
}

.m-fade-down-enter-active,
.m-fade-down-leave-active,
.m-fade-left-enter-active,
.m-fade-left-leave-active,
.m-fade-right-enter-active,
.m-fade-right-leave-active,
.m-fade-up-enter-active,
.m-fade-up-leave-active {
  transition-property: opacity, transform;
}

.m-fade-up-enter,
.m-fade-up-leave-to {
  transform: translate3d(0, 100%, 0);
  opacity: 0
}

.m-fade-down-enter,
.m-fade-down-leave-to {
  transform: translate3d(0, -100%, 0);
  opacity: 0
}

.m-fade-left-enter,
.m-fade-left-leave-to {
  transform: translate3d(-100%, 0, 0);
  opacity: 0
}

.m-fade-right-enter,
.m-fade-right-leave-to {
  transform: translate3d(100%, 0, 0);
  opacity: 0
}


.m-popover__action {
  &:active {
    background-color: rgba(0, 0, 0, 0.2);
  }

  &--disabled {
    color: var(--van-popover-dark-action-disabled-text-color);

    &:active {
      background-color: transparent;
    }
  }
}

</style>
